package org.zgr.service;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import common.constant.user.LoginConstants;
import common.dtos.LoginDto;
import common.dtos.RegisterDto;
import common.dtos.ResponseResult;
import common.entity.user.User;
import common.enums.HttpCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Service;
import org.zgr.mapper.UserMapper;
import utils.MD5Util;
import utils.SaltUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: 郑国荣
 * @Date: 2023-12-31-19:03
 * @Description:
 */
@Service
@Import({RedisService.class})
public class UserServiceImpl extends ServiceImpl<UserMapper, User> {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisService redisService;


    public ResponseResult login(LoginDto loginDto, String token) {
        User user = this.loginCheck(loginDto);
        if (user == null) {
            return ResponseResult.get(HttpCodeEnum.LOGIN_INFO_ERROR);
        }
        StpUtil.setTokenValue(token);
        StpUtil.login(user.getUserId());
        System.out.println(StpUtil.getSessionByLoginId(user.getUserId()));

        // todo 生成用户权限并保存到redis中
        redisService.setCacheObject("user:" + user.getUserId(), user);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        Map<String, Object> map = new HashMap<>();
        map.put("userId", user.getUserId());
        map.put("userNick", user.getUserNick());
        map.put("mobilePhone", user.getMobilePhone());
        map.put("pwdLen", user.getPwd().length());
        map.put("token", tokenInfo);
        System.out.println("登录成功");
        return new ResponseResult<>(HttpCodeEnum.SUCCESS, "登录成功", map);
    }

    public ResponseResult loginOut(int id) {
        boolean isLogin = StpUtil.isLogin(id);
        if (!isLogin) {
            return ResponseResult.get(HttpCodeEnum.NEED_LOGIN);
        }
        StpUtil.logout(id);
        redisService.deleteObject("user:" + id);
        return ResponseResult.get(HttpCodeEnum.SUCCESS, "登出成功！");
    }

    public ResponseResult register(RegisterDto registerDto) {
        if (registerDto == null) {
            return ResponseResult.get(HttpCodeEnum.PARAM_REQUIRE);
        }
        User user = this.registerCheck(registerDto);
        if (user != null) {
            return ResponseResult.get(HttpCodeEnum.PHONE_EXIST);
        }

        // todo 稍显繁琐，以后再改，可以考虑是否通过捕获异常的方式
        if (registerDto.getPassword().length() < 6) {
            return ResponseResult.get(HttpCodeEnum.PARAM_INVALID, "密码长度不能小于6位");
        }
        if (registerDto.getPassword().length() > 16) {
            return ResponseResult.get(HttpCodeEnum.PARAM_INVALID, "密码长度不能大于16位");
        }
        if (registerDto.getUser_nick().isEmpty()) {
            return ResponseResult.get(HttpCodeEnum.PARAM_INVALID, "昵称长度不能小于1位");
        }
        if (registerDto.getUser_nick().length() > 16) {
            return ResponseResult.get(HttpCodeEnum.PARAM_INVALID, "昵称长度不能大于16位");
        }
        if (registerDto.getAccount()==null || registerDto.getAccount().length() != 11) {
            return ResponseResult.get(HttpCodeEnum.PARAM_INVALID, "手机号格式不正确");
        }
        User newUser = new User();
        String pwd = registerDto.getPassword();
        String salt = SaltUtil.getSalt(8);
        String pwd_salt = MD5Util.encodeWithSalt(pwd, salt);
        //装箱
        newUser.setUserNick(registerDto.getUser_nick());
        newUser.setMobilePhone(registerDto.getAccount());
        newUser.setPwd(pwd_salt);
        newUser.setPwdSalt(salt);
        newUser.setRegisterIp(registerDto.getRegisterIp());
        try {
            userMapper.insert(newUser);
        } catch (Exception e) {
            return new ResponseResult(HttpCodeEnum.REGISTER_SUCCESS, "注册失败");
        }

        return ResponseResult.get(HttpCodeEnum.SUCCESS, "注册成功");
    }

    public User loginCheck(LoginDto loginDto) {
        String account = loginDto.getAccount();
        String password = loginDto.getPassword();
        Short signType = LoginConstants.USERNAME_LOGIN;
        if (account.contains("@")) {
            signType = LoginConstants.EMAIL_LOGIN;
        } else if (account.length() == 11) {
            signType = LoginConstants.PHONE_LOGIN;
        }
        User user;
        switch (signType) {
            case 1:
                user = userMapper.selectOne(new QueryWrapper<User>().eq("mobile_phone", account));
                System.out.println("user:"+user);
                System.out.println("手机号登录");
                break;
            case 2:
                user = userMapper.selectOne(new QueryWrapper<User>().eq("user_nick", account));
                System.out.println("邮箱登录");
                break;
            default:
                System.out.println("用户名登录");
                return null;
        }
        String salt = user.getPwdSalt();
        String password_salt = MD5Util.encodeWithSalt(password, salt);
        System.out.println("password_salt:"+password_salt);
        boolean checkPwd = user.getPwd().equals(password_salt);
        System.out.println("checkPwd:"+checkPwd);
        if (checkPwd) {
            // 更新updateIp
            user.setUpdateIp(loginDto.getUpdateIp());
            userMapper.updateById(user);
            return user;
        }
        return null;
    }

    public User registerCheck(RegisterDto registerDto) {
        // todo 其他检查，以及notblank注解无效的话
        String account = registerDto.getAccount();
        // 检查账号是否已经注册
        return userMapper.selectOne(new UpdateWrapper<User>().eq("mobile_phone", account));
    }


}
